import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, In } from 'typeorm';
import { SysUserWithRoleEntity } from '../user/entities/user-width-role.entity';
import { SysRoleWithMenuEntity } from '../role/entities/role-width-menu.entity';
import { SysMenuEntity } from '../menu/entities/menu.entity';
import { SysRoleEntity } from '../role/entities/role.entity';
import { Uniq } from 'src/common/utils';

@Injectable()
export class UserPermissionService {
  constructor(
    @InjectRepository(SysUserWithRoleEntity)
    private readonly userRoleRepo: Repository<SysUserWithRoleEntity>,
    @InjectRepository(SysRoleWithMenuEntity)
    private readonly roleMenuRepo: Repository<SysRoleWithMenuEntity>,
    @InjectRepository(SysMenuEntity)
    private readonly menuRepo: Repository<SysMenuEntity>,
    @InjectRepository(SysRoleEntity)
    private readonly roleRepo: Repository<SysRoleEntity>,
  ) {}

  /**
   * 获取用户的角色 ID 列表
   */
  async getRoleIds(userId: number): Promise<number[]> {
    const rels = await this.userRoleRepo.find({ where: { userId } });
    return Uniq(rels.map((r) => r.roleId));
  }

  /**
   * 获取用户角色实体列表
   */
  async getRoles(userId: number): Promise<SysRoleEntity[]> {
    const roleIds = await this.getRoleIds(userId);
    return await this.roleRepo.find({ where: { delFlag: '0', roleId: In(roleIds) } });
  }

  /**
   * 获取用户的权限列表（菜单 perms 字段）
   */
  async getPermissions(userId: number): Promise<string[]> {
    if (userId === 1) {
      return ['*:*:*'];
    }
    const roleIds = await this.getRoleIds(userId);
    const roles = await this.roleMenuRepo.find({ where: { roleId: In(roleIds) } });
    const menuIds = Uniq(roles.map((r) => r.menuId));

    const menus = await this.menuRepo.find({
      where: { delFlag: '0', status: '0', menuId: In(menuIds) },
      select: ['perms'],
    });

    return Uniq(menus.map((m) => m.perms).filter(Boolean));
  }

  /**
   * 获取用户菜单 ID 列表（含超管判断）
   */
  async getMenuIds(userId: number): Promise<number[]> {
    const roleIds = await this.getRoleIds(userId);
    if (roleIds.includes(1)) {
      const all = await this.menuRepo.find({ where: { delFlag: '0', status: '0' }, select: ['menuId'] });
      return all.map((m) => m.menuId);
    }

    const rels = await this.roleMenuRepo.find({ where: { roleId: In(roleIds) } });
    return Uniq(rels.map((r) => r.menuId));
  }
}
